// requestProxy.ts
import express from 'express'
import axios from 'axios'
import getPort from 'get-port'
import store from '../store/index';
import log from 'electron-log'
import type { AxiosRequestConfig } from 'axios'
import fs from 'fs'
import path from 'path'
import os from 'os'
import yaml from 'js-yaml'

// 接口地址和token
let token = ''
let targetUrl = ''

// 配置文件路径 (动态获取 AppData 路径)
function getConfigPath() {
  return path.join(os.homedir(), 'AppData', 'Roaming', 'Blade', 'config.yml')
}

// 从配置文件读取 token
function loadTokenFromConfig() {
  try {
    const configPath = getConfigPath()
    if (!fs.existsSync(configPath)) {
      log.warn('配置文件不存在:', configPath)
      return
    }

    const fileContent = fs.readFileSync(configPath, 'utf8')
    const config = yaml.load(fileContent) as any

    if (config?.api_cookies) {
      token = config.api_cookies
      log.info('从配置文件加载 Token 成功')
    } else {
      log.warn('配置文件中未找到 token 字段')
    }

    if (config?.arthub_service_url) {
      targetUrl = config.arthub_service_url
      log.info('从配置文件加载 arthub_service_url 成功' + config.arthub_service_url)
    } else {
      log.warn('配置文件中未找到 arthub_service_url 字段')
    }

  } catch (err: any) {
    log.error('读取配置文件失败:', err.message)
  }
}

// 监听配置文件变化，自动更新 token
function watchConfigFile() {
  const configPath = getConfigPath()
  if (!fs.existsSync(configPath)) {
    log.warn('配置文件不存在，无法监听:', configPath)
    return
  }

  log.info('开始监听配置文件:', configPath)

  fs.watch(configPath, { persistent: false }, (eventType) => {
    if (eventType === 'change') {
      log.info('检测到配置文件变化，重新加载 Token...')
      loadTokenFromConfig()
    }
  })
}

// 提供一个更新 token 的方法
export function setProxyToken(newToken: string) {
  token = newToken
  log.info('更新代理 Token:', token)
}

export async function createProxyServer() {
  const app = express()
  app.use(express.json())
  log.info('创建代理服务')

  // 启动时先加载 token
  loadTokenFromConfig()
  // 启动文件监听
  watchConfigFile()

  // CORS：允许渲染进程来源跨域访问
  app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*') // 开发环境可放开；如需严格控制改为具体域
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization')
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS')
    if (req.method === 'OPTIONS') return res.sendStatus(204)
    next()
  })

  // 获取一个未被占用的端口
  const getPortFn = (getPort as any)?.default ?? (getPort as any)
  const port = await getPortFn({ port: Array.from({ length: 101 }, (_, i) => 3000 + i) })

  // 代理所有 /api/* 请求（修复 path-to-regexp 写法）
  app.use('/api', async (req, res) => {
    const path = req.originalUrl.replace(/^\/api/, '') // 去掉前缀 /api
    const url = `${targetUrl}${path}`
    log.info(`代理请求: [${req.method}] ${url}`)

    try {
      const axiosConfig: AxiosRequestConfig = {
        method: req.method as any,
        url,
        headers: {
          ...req.headers,
          host: new URL(targetUrl).host, // 避免 host 错误
          cookie: token, // 强制带上 token
        },
        data: req.body,
        params: req.query,
        timeout: 10000,
        validateStatus: () => true, // 不要抛错，让我们自己处理
      }

      const response = await axios(axiosConfig)

      // 转发响应
      res.status(response.status).set(response.headers as any).send(response.data)
    } catch (err: any) {
      log.error('代理请求失败:', err.message)
      res.status(500).json({ error: '代理请求失败', detail: err.message })
    }
  })

  // 启动服务
  const server = app.listen(port, '127.0.0.1', () => {
    try {
      store.set('proxyPort', port)
      log.info(`代理服务已启动: http://127.0.0.1:${port}`)
    } catch (e) {
      console.error('保存端口失败:', e)
    }
  })

  // 错误处理
  server.on('error', (err) => {
    log.info('代理服务启动失败:', err)
  })
  
  return port
}
